package v1

import (
	"encoding/json"
	"fmt"
	"time"

	metav1 "gitee.com/youkelike/ziam/zapi/meta/v1"
	"gitee.com/youkelike/ziam/zutils/auth"
	"gitee.com/youkelike/ziam/zutils/idutil"
	"gorm.io/gorm"
)

type User struct {
	// May add TypeMeta in the future.
	// metav1.TypeMeta `json:",inline"`

	// 内嵌一个结构
	metav1.ObjectMeta `json:"metadata,omitempty"`

	Status int `json:"status" gorm:"column:status" validate:"omitempty"`

	// Required: true
	Nickname string `json:"nickname" gorm:"column:nickname" validate:"required,min=1,max=30"`

	// Required: true
	Password string `json:"password,omitempty" gorm:"column:password" validate:"required"`

	// Required: true
	Email string `json:"email" gorm:"column:email" validate:"required,email,min=1,max=100"`

	// Required: true
	Phone string `json:"phone" gorm:"column:phone" validate:"omitempty"`

	IsAdmin int `json:"isAdmin,omitempty" gorm:"column:isAdmin" validate:"omitempty"`

	TotalPolicy int64 `json:"totalPolicy" gorm:"-" validate:"omitempty"`

	LoginedAt time.Time `json:"loginedAt,omitempty" gorm:"column:loginedAt"`
}

type UserList struct {
	// May add TypeMeta in the future.
	// metav1.TypeMeta `json:",inline"`

	// Standard list metadata.
	// +optional
	metav1.ListMeta `json:",inline"`

	Items []*User `json:"items"`
}

// TableName maps to mysql table name.
func (u *User) TableName() string {
	return "user"
}

func (u *User) Compare(pwd string) (err error) {
	if err = auth.Compare(u.Password, pwd); err != nil {
		return fmt.Errorf("failed to compile password: %w", err)
	}

	return
}

// BeforeCreate run before create database record.
func (u *User) BeforeCreate(tx *gorm.DB) (err error) {
	// u.Password, err = auth.Encrypt(u.Password)
	u.ExtendShadow = u.Extend.String()

	return
}

// AfterCreate run after create database record.
func (u *User) AfterCreate(tx *gorm.DB) (err error) {
	// 只是把 u.ID 进行了简单的加密
	u.InstanceID = idutil.GetInstanceID(u.ID, "user-")

	return tx.Save(u).Error
}

// BeforeUpdate run before update database record.
func (u *User) BeforeUpdate(tx *gorm.DB) (err error) {
	u.Password, err = auth.Encrypt(u.Password)
	u.ExtendShadow = u.Extend.String()

	return err
}

// AfterFind run after find to unmarshal a extend shadown string into metav1.Extend struct.
func (u *User) AfterFind(tx *gorm.DB) (err error) {
	if err := json.Unmarshal([]byte(u.ExtendShadow), &u.Extend); err != nil {
		return err
	}

	return nil
}
